#include "MouseDrag.h"
#include "Widgets/Mouse/MouseWidget.h"
#include "Widgets/WidgetTree.h"

void RMouseDrag::StopDrag()
{
    //stop drag
    bIsDragging=false;

    OnDragEnded.ExecuteIfBound();
}

void RMouseDrag::StartDrag(CWidgetTree* InTree)
{
    CurrentTarget=Target.Get();  

    bIsDragging=true;

    StartDragMousePosition= InTree->GetMousePositionInContent();
    OnDragStarted.ExecuteIfBound();

    if(CurrentTarget)
    {
        StartDragWidgetPosition=CurrentTarget->PresentAbsPosition;//  Position;
        StartDragWidgetRelativePosition=SVec2(CurrentTarget->X.Get(),CurrentTarget->Y.Get());
    }

      
}

TSharedObjectPtr<RMouseWidget> RMouseDrag::GetOwnerMouse()
{
    return GetOwner();
}

RMouseDrag::~RMouseDrag()
{
    if(bIsDragging)
    {
        StopDrag();
    }
}

bool RMouseDrag::ProcessMouseEvent(CWidgetTree* InTree,const SMouseButtonEvent& MouseEvent)
{
    if(!bIsDragging)
    {
        if(MouseEvent.GetType()==EMouseEventType::ButtonDown
            && !MouseEvent.IsDoubleClick()
        )
        {
            //try to start detect drag
            //detect might be covored by other mouse widget
            if(!InTree->IsDetecting())
            {
                InTree->StartDetect(this);
            }
            return false;
        }        

    }
    else  if(MouseEvent.GetType()==EMouseEventType::Move)
    {
        SVec2 TotalMouseMoveDistance=InTree->GetMousePositionInContent()-StartDragMousePosition;
        switch(Direction.Get())
        {
            case EDragDirection::Both:
            {
                if(CurrentTarget)
                {
                    auto Position=StartDragWidgetPosition+TotalMouseMoveDistance;
                    auto LocalPosition=CurrentTarget->ToLocalPosition(Position)- CurrentTarget->ToLocalPosition(StartDragWidgetPosition);
                    CurrentTarget->X= CMathBase::Clamp(StartDragWidgetRelativePosition.X+ LocalPosition.X,TargetWidgetMinX.Get(),TargetWidgetMaxX.Get());
                    CurrentTarget->Y=CMathBase::Clamp(StartDragWidgetRelativePosition.Y+LocalPosition.Y,TargetWidgetMinY.Get(),TargetWidgetMaxY.Get());
                }
            }
                break;
            case EDragDirection::Horizontal:
                {
                    TotalMouseMoveDistance.Y=0;
                    if(CurrentTarget)
                    {
                        float X=StartDragWidgetPosition.X+TotalMouseMoveDistance.X;
                        float LocalXDelta=CurrentTarget->ToLocalPosition(SVec2(X,0)).X-CurrentTarget->ToLocalPosition(StartDragWidgetPosition).X;
                        CurrentTarget->X=CMathBase::Clamp(StartDragWidgetRelativePosition.X+LocalXDelta,TargetWidgetMinX.Get(),TargetWidgetMaxX.Get());
                    }

                    break;    
                }
            case EDragDirection::Vertical:
            {
                TotalMouseMoveDistance.X=0;
                if(CurrentTarget)
                {
                    float Y=StartDragWidgetPosition.Y+TotalMouseMoveDistance.Y;
                    float LocalYDelta=CurrentTarget->ToLocalPosition(SVec2(0,Y)).Y -CurrentTarget->ToLocalPosition(StartDragWidgetPosition).Y;
                    CurrentTarget->Y=CMathBase::Clamp(StartDragWidgetRelativePosition.Y+LocalYDelta,TargetWidgetMinY.Get(),TargetWidgetMaxY.Get());
                }
            }
                break;                    
        };
        OnDragMoved.ExecuteIfBound(TotalMouseMoveDistance);

        //WH::Cout()<<"xdelta:" <<TotalMouseMoveDistance.X<<"ydelte:" <<TotalMouseMoveDistance.Y<<WH::EndL();
        return true;
    }

    

    return false;

}